package com.marion.study.service;

import com.marion.study.entity.UserEntity;
import com.marion.study.repo.read.UserReadRepo;
import com.marion.study.repo.write.ProductWriteRepo;
import com.marion.study.repo.write.UserAssetWriteRepo;
import com.marion.study.repo.write.UserWriteRepo;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.boot.SpringApplication;
import org.springframework.context.ApplicationContext;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Isolation;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.util.List;

@Service
public class UserService {

    private final UserWriteRepo userWriteRepo;

    private final UserReadRepo userReadRepo;

    private final UserAssetWriteRepo userAssetWriteRepo;

    private final ProductWriteRepo productWriteRepo;

    private final ApplicationContext applicationContext;

    public UserService(UserWriteRepo userWriteRepo, UserReadRepo userReadRepo, UserAssetWriteRepo userAssetWriteRepo, ProductWriteRepo productWriteRepo, ApplicationContext applicationContext) {
        this.userWriteRepo = userWriteRepo;
        this.userReadRepo = userReadRepo;
        this.userAssetWriteRepo = userAssetWriteRepo;
        this.productWriteRepo = productWriteRepo;
        this.applicationContext = applicationContext;
    }

    public List<UserEntity> getUserFromWrite() {
        return userWriteRepo.findAll();
    }

    public List<UserEntity> getUserFromRead() {
        return userReadRepo.findAll();
    }

    /**
     * 事务传播性
     * 1. 用户下单，扣除余额，扣减库存
     */
    @Transactional(rollbackFor = Exception.class,
            isolation = Isolation.READ_COMMITTED,
            propagation = Propagation.REQUIRED)
    public void order(long uid, int produceId) {
        UserService userService = applicationContext.getBean(UserService.class);
        userService.reduceAmount(uid);
        userService.reduceInventory(produceId);
    }

    /**
     * 扣除用户余额10元
     */
    @Transactional(rollbackFor = Exception.class,
            isolation = Isolation.READ_COMMITTED,
            propagation = Propagation.REQUIRED)
    public void reduceAmount(long uid) {
        userAssetWriteRepo.reduceAmount(uid, 10);
    }

    /**
     * 扣除库存1个
     */
    @Transactional(rollbackFor = Exception.class,
            isolation = Isolation.READ_COMMITTED,
            propagation = Propagation.REQUIRED)
    public void reduceInventory(int produceId) {
        productWriteRepo.reduceInventory(produceId, 1);
        if (produceId == 1) {
            throw new RuntimeException("reduce inventory failed");
        }
    }

}
